iT邦幫忙

2021 iThome 鐵人賽

DAY 8
0

簡單介紹一下變數在JS中的幾個性質,之後的篇章會比較深入的講解,這些性質背後的原因們


看變數的值,決定是數字、字串還是...

var a=1;
var b='2'
var c=function(){return 3}
var d=false

console.log(typeof a);  //number
console.log(typeof b);  //string
console.log(typeof c);  //function
console.log(typeof d);  //boolean

JS不像Java一樣用int, String, boolean等關鍵字宣告變數。
JS的變數在ES6以前只有var,ES6以後也頂多新增了let, const,變數的typeof都需要等到賦值才能決定。

var a;
console.log(a);        //undefined
console.log(typeof a); //undefined

用var宣告變數,初始化為undefined。還沒賦值前,無法判斷該變數的type

小結論:變數的type,用變數的value判斷


var變數的有效範圍

有效範圍講的專業一點叫作用域(scope),var變數是遵照 function scope

甚麼是 有效範圍 或 作用域

就是變數存在的地方。

有點像寄生物與宿主的關係,寄生物離開宿主多久就會死掉。
變數離開他的作用域,就會被垃圾回收機制給丟掉。燈燈燈燈燈燈燈燈燈,垃圾車來囉~

甚麼是「var變數遵照 function scope

講人話就是:var關鍵字令出的變數,他的有效範圍以function界定。

console.log('用var關鍵字 定義變數i')
console.log('--------------------------')

var i='全域變數';
console.log(`i=${i}`);  
//`i=${i}` 等價於 'i='+i 字串連接
// ` 反引號在~鍵上面 (我一開始還找不到,所以特別寫這行)
console.log('--------------------------')

function fun(){
	var i='function內變數';
	console.log(`I'm in the function, i=${i}`)
};
fun(); 
console.log('--------------------------')
        
console.log(`I'm out of the function, i=${i}`);  
console.log('--------------------------')
        
console.log("I'm in the for loop")
for(var i=0;i<5;i++){
	console.log(`i=${i}`) 
}  //i=5離開for迴圈
console.log('--------------------------')

console.log(`I'm out of the for loop, i=${i}`); 
用var關鍵字 定義變數i
--------------------------
i=全域變數
--------------------------
I'm in the function, i=function內變數
--------------------------
I'm out of the function, i=全域變數
--------------------------
I'm in the for loop
i=0
i=1
i=2
i=3
i=4
--------------------------
I'm out of the for loop, i=5

離開for loop後,我們再次呼叫變數i,得到的答案是:5。

原因是for loop 不是function,會影響到在全域var定義的變數i

呼叫自己沒有定義的變數

var i='全域變數';
function outterFun(){
	function innerFun(){
			console.log(i)
	}
	return innerFun;
};

aNewFun=outterFun();       
aNewFun();   //全域變數
  • outterFun裡面的inner function,找不到變數i → 往外向outterFun
    outterFun找不到變數i →向全域
  • 全域也沒有,報錯Uncaught ReferenceError: i is not defined

小結論:

  • var變數遵照 function scope
  • function內,叫得到外面的變數;function外,叫不到內變數

屬性與變數有仝款某(有一樣嗎)?

首先先來釐清變數和屬性,他們有以下幾個關係:

  • 一般情況,變數放在一個object裡面,那該變數就會叫object的屬性

  • function雖然是一個object,但var變數的作用域(scope)是以function為界,

    所以function外,別想拿到function的內變數

  • function外,如果硬要存取內變數,可以把它從function return出來,變得與function本身同級。

  • function外,可以存取屬性。
    沒錯,你沒看錯,function可以有屬性,因為function是object嘛~~

function aFun(){
        let a='function內變數';
        return a;   //可以透過return,讓function外,可以取出內變數
    }
aFun.a='function物件屬性';
console.log(`aFun.a= ${aFun.a}`)    // aFun.a= function物件屬性
console.log(`aFun return a= ${aFun()}`);   //aFun return a= function內變數

小結論:

  • 可被造訪的object屬性稱為object變數
  • 在function外,不要想直接存取function的內變數,因為var變數遵照 function scope
  • 在function外,可以存取function的屬性,或是被return出來的function內變數

提升(Hoisting)簡單版

console.log(a);
fun();
console.log('----------')
function fun(){
	console.log(b)
	var b=2;
}
var a=1;

var變數提升:

  • 提到function或全域的頂部
  • 建立(實例化)變數+初始化undefined

function變數提升:

  • 提到function或全域的頂部
  • 整個function body一起提升
    (其實是預編譯,沒有一起提升,後面的文章會介紹,別急齁~)

在JS眼裡,上面那一串的順序會變成

var a;    //初始化undefined
function fun(){
	var b	 //初始化undefined
	console.log(b)
	b=2;
}

console.log(a);   //undefined
fun();            //undefined
console.log('----------')
a=1;
console.log(a);   //1

練個手感吧

var a='全域a'; 

console.log(`a=${a}`)
console.log(`a=${fun('實參')}`)
outerfun();
fun1();
          
function outerfun(){
	a='在outerfun中改a值'
	var a='outterfun a'
	for(var a=0;a<5;a++){
		console.log(`a=${a}`?)
		a='for loop裡面的a'
		console.log(`a=${a}`)
	}
	console.log(`a=${a}`);
	function innerfun(){
		console.log(`a=${a}`);
	}
	innerfun();
}

function fun(a){
	return a;
}
function fun1(){
	a='在fun1中改a值'
}

console.log(`a=${a}`)

小提醒:變數前面沒寫var,要嘛是引用自己或是引用外層的變數,
要嘛就是新建全域變數,但這種不會提升

.

.

.

.

.

.

.

.

.

.

.

a=全域a
a=實參
a=0
a=for loop裡面的a
a=NaN
a=NaN
a=在fun1中改a值
//模擬:for迴圈裡的a
var num='我是字串,我要先被加1,再被轉成number'
num+=1                  //'我是字串,我要先被加1,再被轉成number1'
num =Number(num)        //string轉number
console.log(num)        //NaN
console.log(typeof num) //number

//模擬:判斷是否離開for迴圈
//句型:(判斷句)?true執行:fales執行
console.log((NaN<5)?'yes':'no')  //no,離開for迴圈

a在各個function scope中,被改值的過程

  • 全域的a:'全域a'
    →'在fun1中改a值'
  • fun的a:'實參'(參數值)
  • outterfun的a:'在outerfun中改a值'
    →'outterfun a'
    →a=0
    →'for loop裡面的a'
    →NaN(字串加1,再轉number)
  • innerfun的a:NaN(引用outerfun的)

上一篇
DAY7 淺扒網路 - 估計被扒皮的是我不是網路
下一篇
DAY9 樣式屬性權重 - Nav Bar實作之遇到的小卡頓
系列文
前端幼鳥三十天養成記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言